#include <iostream>
#include <process.h>

#include <remotefunction.h>

#include <windows.h>


bool g_isServer = true;
const std::string g_pipename = "\\\\.\\pipe\\testmt";

kog::remote_function* g_rf = NULL;

int add(int a, int b)
{
	return a + b;
}

void call(void* param)
{
	kog::remote_function* rf = (kog::remote_function*)param;
	const char* ptr = g_isServer ? "server" : "client";
	//for (int i = 0; i < 10; ++ i)
	while (true)
	{
		try {
			int a = rand();
			int b = rand();
			int c = (*rf)["add"].makecall<int>(a, b);

			if (add(a, b) != c)
			{
				printf("[%s] error %d + %d != %d\n", ptr, a, b, c);
			}
			else printf("[%s] %d + %d == %d\n", ptr, a, b, c);
		} catch (std::exception& ex) {
			printf("[%s] exception (%s)\n", ptr, ex.what());
			break;
		}
	}
	printf("[%s] call done.\n", ptr);
}

void server(void* param)
{
	kog::pipe pipeServer(g_pipename, kog::pipe::server_port);
	pipeServer.waitclient();
	

	int fid, tid, dtype;
	kog::pipe::msgpeice_t msg;
	pipeServer.recv(fid, tid, dtype, msg);
	printf("[server] recv (%d -> %d) %s\n", fid, tid, msg.ptr);
	delete msg.ptr;

	kog::remote_function rfServer(pipeServer);
	rfServer.entry("add", add);

	g_rf = &rfServer;
	// start call thread
	_beginthread(call, 0, &rfServer);
	_beginthread(call, 0, &rfServer);
	
	rfServer.start_service();
	

	printf("server done.\n");
}

void client(void* param)
{
	Sleep(200);
	kog::pipe pipeClient(g_pipename, kog::pipe::client_port);
	pipeClient.connectserver();
	const char* tmp = "Hello, world!";
	kog::pipe::msgpeice_t m;
	m.ptr = tmp;
	m.len = strlen(tmp) + 1;
	pipeClient.send(0, 1, 0, &m, 1);

	kog::remote_function rfClient(pipeClient);
	rfClient.entry("add", add);

	g_rf = &rfClient;
	_beginthread(call, 0, &rfClient);
	_beginthread(call, 0, &rfClient);
	
	rfClient.start_service();

	printf("client done.\n");
}


int main(int argc, const char* argv[])
{
	typedef void (*thread_fun)(void*);

	
	thread_fun fun = NULL;
	if (argc == 1) // parent
	{
		printf("server\n");
		std::string cmd = '"' + std::string(argv[0]) + '"' + " 1";
		std::vector<char> buf(cmd.begin(), cmd.end());
		buf.push_back('\0');

		STARTUPINFOA si;
		memset(&si, 0, sizeof(STARTUPINFO));
		si.cb = sizeof(STARTUPINFO);
		si.dwFlags = STARTF_USESHOWWINDOW;
		si.wShowWindow = SW_SHOW;
		PROCESS_INFORMATION pi;
		::CreateProcessA(NULL, &buf[0], NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);

		fun = server; 
	}
	else
	{
		printf("client\n");
		g_isServer = false;
		fun = client;
	}

	kog::os::osobject hserver;
	hserver.create_thread(kog::unary2zero(std::ptr_fun(fun), (void*)NULL));

	Sleep(5 * 1000);
	g_rf->stop_service();

	system("pause");

	return 0;
}